home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / main.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  37KB  |  1,178 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. from __future__ import with_statement
  5. import os.path as os
  6. import wx
  7. import sys
  8. import logging
  9. import platform
  10. from time import time
  11. from path import path
  12. from traceback import print_exc, print_stack
  13. from contextlib import closing
  14. from logging import getLogger
  15. log = getLogger()
  16. IDLE_CHECK_MS = 2000
  17. IDLE_CHECK_MOUSE_DISTANCE = 10
  18. LOG_FILENAME = 'digsby.log.csv'
  19. LOG_SPEED_LIMIT = 0.4 * 1024 * 1024
  20. LOG_SPEED_WINDOW = 10
  21. USE_HANGING_THREAD_DAEMON = True
  22. EXIT_TIMEOUT_SECS = 10
  23. TASKBAR_REFRESH_MS = 5 * 60 * 1000
  24. if not getattr(sys, 'REVISION', 'dev') != 'dev' and '--multi' not in sys.argv:
  25.     pass
  26. USE_SINGLE_INSTANCE = '--single' in sys.argv
  27. APP_NAME = u'Digsby'
  28.  
  29. def init_threadpool():
  30.     if getattr(wx, 'WXPY', False):
  31.         add_before_cb = add_before_cb
  32.         add_after_cb = add_after_cb
  33.         import util.threads
  34.         add_before_cb(wx.SipNewThread)
  35.         add_after_cb(wx.SipEndThread)
  36.     
  37.     ThreadPool = ThreadPool
  38.     import util
  39.     ThreadPool(5)
  40.  
  41. if USE_SINGLE_INSTANCE:
  42.     from singleinstance import SingleInstanceApp
  43.     DigsbyAppBase = SingleInstanceApp
  44. else:
  45.     DigsbyAppBase = wx.App
  46.  
  47. class DigsbyApp(DigsbyAppBase):
  48.     
  49.     def OnFatalException(self):
  50.         
  51.         try:
  52.             where_string = where_string
  53.             import common.commandline
  54.             print >>sys.stderr, where_string(duplicates = True)
  55.             sys.stderr.flush()
  56.         except Exception:
  57.             e = None
  58.             print_exc()
  59.  
  60.  
  61.     
  62.     def __init__(self):
  63.         if USE_SINGLE_INSTANCE:
  64.             DigsbyAppBase.__init__(self, appname = APP_NAME, redirect = False)
  65.         else:
  66.             DigsbyAppBase.__init__(self, redirect = False)
  67.         self.global_hotkeys = { }
  68.         self.next_hotkey_id = 0
  69.         self.PreShutdown = []
  70.  
  71.     
  72.     def Restart(self):
  73.         self.restarting = True
  74.         self.DigsbyCleanupAndQuit()
  75.  
  76.     
  77.     def AfterStartup(self):
  78.         if getattr(self, '_afterstartup', False):
  79.             return None
  80.         
  81.         self._afterstartup = True
  82.         log.info('AfterStartup')
  83.         import socks as socks
  84.         import util
  85.         import wx
  86.         import util.callbacks as util
  87.         util.callbacks.register_call_later('MainThread', wx.CallAfter)
  88.         socks.setdefaultproxy(**util.GetProxyInfo())
  89.         if 'wxMSW' in wx.PlatformInfo:
  90.             self.setup_fullscreen()
  91.         
  92.         self.init_hotkeys()
  93.         init_threadpool()
  94.         import wx
  95.         if 'wxMSW' in wx.PlatformInfo and sys.opts.cpuwatch:
  96.             CPUWatch = CPUWatch
  97.             import util.perfmon
  98.             self.cpu_watcher = CPUWatch()
  99.         
  100.         
  101.         try:
  102.             
  103.             try:
  104.                 import webview as webview
  105.             except ImportError:
  106.                 import wx.webview as wx
  107.  
  108.         except Exception:
  109.             print >>sys.stderr, 'Warning: error preloading webkit'
  110.  
  111.         if 'wxMSW' in wx.PlatformInfo:
  112.             import util.checkoptions as util
  113.             util.checkoptions.start_checking()
  114.         
  115.  
  116.     
  117.     def OnInit(self):
  118.         set_app_info(self)
  119.         self.Bind(wx.EVT_POWER_SUSPENDED, self.OnSuspend)
  120.         self.Bind(wx.EVT_POWER_RESUME, self.OnResume)
  121.         self.Bind(wx.EVT_MENU, self.DigsbyCleanupAndQuit, id = wx.ID_EXIT)
  122.         wx.IdleEvent.SetMode(wx.IDLE_PROCESS_SPECIFIED)
  123.         wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_SPECIFIED)
  124.         wx.SystemOptions.SetOptionInt('mac.textcontrol-use-mlte', 1)
  125.         wx.SystemOptions.SetOptionInt('mac.textcontrol-use-spell-checker', 1)
  126.         if os.name == 'nt':
  127.             self.setup_crash_reporting()
  128.         
  129.         import stdpaths as stdpaths
  130.         stdpaths.init_wx()
  131.         sys.comtypes_dir = stdpaths.userlocaldata
  132.         self.SetExitOnFrameDelete(False)
  133.         return True
  134.  
  135.     
  136.     def init_plugins_pythonpath(self):
  137.         import stdpaths
  138.         sys.path.extend((lambda .0: for p in .0:
  139. p.abspath())((stdpaths.userdata / 'Plugins').files('*.egg')))
  140.  
  141.     
  142.     def GetCmdLine(self):
  143.         exe = sys.executable.decode(sys.getfilesystemencoding())
  144.         if getattr(sys, 'frozen', False) == 'windows_exe':
  145.             args = sys.argv[1:]
  146.         else:
  147.             args = sys.argv[:]
  148.         return ' '.join([
  149.             exe] + args)
  150.  
  151.     
  152.     def setup_crash_reporting(self, username = None):
  153.         if not sys.opts.crashreporting:
  154.             print >>sys.stderr, 'Crash reporting is disabled.'
  155.             return None
  156.         
  157.         crash_cmd = self.GetCmdLine()
  158.         crash_cmd += ' --crashreport %s'
  159.         if username is not None:
  160.             crash_cmd += ' --crashuser %s' % username
  161.         
  162.         self.SetCrashCommand(crash_cmd)
  163.         if sys.opts.full_crashdump:
  164.             flag = wx.CRASH_REPORT_LOCATION | wx.CRASH_REPORT_STACK | wx.CRASH_REPORT_LOCALS | wx.CRASH_REPORT_GLOBALS
  165.             self.crash_report_flags = flag
  166.         
  167.         crashdump_dir = sys.opts.crashdump_dir
  168.         if crashdump_dir:
  169.             isdir = isdir
  170.             abspath = abspath
  171.             pathjoin = join
  172.             normpath = normpath
  173.             import os.path
  174.             
  175.             try:
  176.                 crashdump_dir = abspath(crashdump_dir)
  177.                 if not isdir(sys.opts.crashdump_dir):
  178.                     os.makedirs(crashdump_dir)
  179.             except Exception:
  180.                 print_exc()
  181.  
  182.             if not username:
  183.                 pass
  184.             filename = 'Digsby_%s_%s.dmp' % ('', str(time()))
  185.             filename = normpath(pathjoin(crashdump_dir, filename))
  186.             wx.CrashReport.SetFileName(filename)
  187.             print >>sys.stderr, 'Dumpfile: %r' % wx.CrashReport.GetFileName()
  188.         
  189.         wx.HandleFatalExceptions()
  190.  
  191.     
  192.     def OnSuspend(self, e):
  193.         profile = profile
  194.         import common
  195.         p = profile()
  196.         if p is not None:
  197.             p.hibernate()
  198.         
  199.  
  200.     
  201.     def OnResume(self, e):
  202.         profile = profile
  203.         import common
  204.         p = profile()
  205.         if p is not None:
  206.             p.unhibernate(20)
  207.         
  208.  
  209.     
  210.     def setup_fullscreen(self):
  211.         FullscreenApp = FullscreenApp
  212.         import gui.native.helpers
  213.         imhub = imhub
  214.         import gui.imwin
  215.         RepeatTimer = RepeatTimer
  216.         Delegate = Delegate
  217.         import util
  218.         self.on_fullscreen = Delegate()
  219.         self._fs_app_running = None((RepeatTimer, 1), (lambda : (None, wx.CallAfter)((lambda : self.on_fullscreen(FullscreenApp())))
  220. ))
  221.         self._fs_app_running.start()
  222.         (self.on_fullscreen,) += (lambda val: None if not val else None)
  223.  
  224.     finish_init = False
  225.     
  226.     def ShowSplash(self, autologin_override = None, kicked = False):
  227.         splash = DigsbySplash
  228.         import digsbysplash
  229.         log = getLogger('splash')
  230.         self.OnBuddyListShown = []
  231.         
  232.         def splash_success(info):
  233.             self.AfterStartup()
  234.             import digsbyprofile
  235.             
  236.             def signin_success(on_gui_load):
  237.                 wx.CallAfter(self.FinishInit, on_gui_load)
  238.  
  239.             
  240.             def signin_error(err = (None, None, (None,), None)):
  241.                 if getattr(self, 'finish_init', False):
  242.                     log.info('signin error on reconnect')
  243.                     conn = digsbyprofile.profile
  244.                     oldcon = conn.connection
  245.                     protocol = protocol
  246.                     import common
  247.                     
  248.                     try:
  249.                         conn.connection.offline_reason = protocol.Reasons.CONN_FAIL
  250.                         log.info('conn.connection1 %r', conn.connection)
  251.                     except AttributeError:
  252.                         log.info('conn.connection2 %r', conn.connection)
  253.  
  254.                     conn.offline_changed(None, 'offline_reason', None, protocol.Reasons.CONN_FAIL)
  255.                     
  256.                     try:
  257.                         conn.connection.change_state(protocol.Statuses.OFFLINE)
  258.                         log.info('conn.connection3 %r', conn.connection)
  259.                     except AttributeError:
  260.                         log.info('conn.connection4 %r', conn.connection)
  261.  
  262.                     conn.connection_state_changed(oldcon, 'state', protocol.Statuses.CONNECTING, protocol.Statuses.OFFLINE)
  263.                     conn.account_manager.on_offline_change(conn, None, None, None)
  264.                 else:
  265.                     s.proto_error(err)
  266.  
  267.             return digsbyprofile.signin(info['username'], info['password'], success = signin_success, error = signin_error)
  268.  
  269.         s = splash(splash_success, autologin_override = autologin_override)
  270.         self._splash = s
  271.         self.SetTopWindow(s)
  272.         
  273.         def aftershown():
  274.             s.Show()
  275.             s.Update()
  276.  
  277.         wx.CallAfter(aftershown)
  278.         if kicked:
  279.             wx.CallAfter(wx.MessageBox, message = _('Your digsby password has been changed. Please log back in with the new password.'), caption = _('Password Changed'))
  280.         
  281.         self.finish_init = False
  282.         return True
  283.  
  284.     
  285.     def SetupTaskbarIcon(self):
  286.         BuddyListTaskBarIcon = BuddyListTaskBarIcon
  287.         import gui.buddylist.buddylistframe
  288.         skin = skin
  289.         import gui
  290.         icon = skin.get('AppDefaults.TaskbarIcon')
  291.         self.tbicon = None(BuddyListTaskBarIcon, icon = 'tooltip' if not getattr(sys, 'DEV', None) else 'Digsby DEV')
  292.         if 'wxMSW' in wx.PlatformInfo:
  293.             self.tbicon.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnShowHideBuddylist)
  294.             
  295.             refresh = lambda : self.tbicon.SetIcon(icon)
  296.             self.tray_refresh_timer = wx.PyTimer(refresh)
  297.             self.tray_refresh_timer.StartOneShot(TASKBAR_REFRESH_MS)
  298.         
  299.  
  300.     
  301.     def FinishInit(self, on_gui_load = None):
  302.         import digsbyprofile
  303.         profile = digsbyprofile.profile
  304.         if self.finish_init:
  305.             return profile.connection.change_state(profile.connection.Statuses.ONLINE)
  306.         
  307.         self.finish_init = True
  308.         splash = self._splash
  309.         del self._splash
  310.         if splash.cancelling:
  311.             return profile.disconnect()
  312.         
  313.         
  314.         def get_rid_of_splash():
  315.             
  316.             try:
  317.                 saveWindowPos = saveWindowPos
  318.                 import gui.toolbox
  319.                 saveWindowPos(splash)
  320.                 splash.Show(False)
  321.             finally:
  322.                 splash.Destroy()
  323.  
  324.  
  325.         get_rid_of_splash = (wx.CallAfter,)(get_rid_of_splash)
  326.         autologin = False
  327.         if not wx.GetKeyState(wx.WXK_SHIFT):
  328.             autologin = True
  329.         
  330.         import gui.skin as gui
  331.         gui.textutil.default_font()
  332.         (wx.CallAfter,)((lambda : list(gui.textutil.GetFonts())))
  333.         if 'wxMSW' in wx.PlatformInfo:
  334.             set_comtypes_gendir = set_comtypes_gendir
  335.             import gui.native.win.winutil
  336.             wx.CallAfter(set_comtypes_gendir)
  337.         
  338.         path = path
  339.         import path
  340.         gui.skin.skintree.resource_paths.append(path(wx.StandardPaths.Get().GetUserDataDir()))
  341.         changeskin = gui.skin.set_active
  342.         
  343.         def on_skin_load():
  344.             self.PostSkin(autologin = autologin, success = on_gui_load)
  345.             profile.connection.change_state(profile.connection.Statuses.ONLINE)
  346.             profile._have_connected = True
  347.  
  348.         if os.name == 'nt':
  349.             self.setup_crash_reporting(username = profile.username)
  350.         
  351.         pref = pref
  352.         import common
  353.         changeskin(pref('appearance.skin'), pref('appearance.variant'), callback = on_skin_load)
  354.  
  355.     
  356.     def PostSkin(self, autologin = False, success = None):
  357.         BuddyListFrame = BuddyListFrame
  358.         import gui.buddylist.buddylistframe
  359.         self.buddy_frame = BuddyListFrame(None, title = _('Buddy List'), name = 'Buddy List', style = wx.DEFAULT_FRAME_STYLE | wx.FRAME_NO_TASKBAR)
  360.         
  361.         def muchlater():
  362.             self.idletimer = wx.PyTimer(self.not_idle)
  363.             self.idletimer.Start(IDLE_CHECK_MS)
  364.             
  365.             def show_buddylist_frame():
  366.                 self.buddy_frame.Show(True)
  367.                 self.SetTopWindow(self.buddy_frame)
  368.                 Delegate = Delegate
  369.                 import util
  370.                 Delegate(self.OnBuddyListShown)(autologin = autologin)
  371.                 del self.OnBuddyListShown[:]
  372.                 
  373.                 def memevent():
  374.                     memory_event = memory_event
  375.                     import gui.native
  376.                     memory_event()
  377.  
  378.                 wx.CallLater(60000, memevent)
  379.                 platformName = platformName
  380.                 import config
  381.                 if platformName == 'win':
  382.                     page_out_ram = page_out_ram
  383.                     import gui.native.win.process
  384.                     wx.CallLater(1000, page_out_ram)
  385.                 
  386.  
  387.             wx.CallAfter(show_buddylist_frame)
  388.  
  389.         wx.CallAfter(muchlater)
  390.         self.SetupTaskbarIcon()
  391.  
  392.     
  393.     def MacOpenFile(self, filename):
  394.         log.info('File dragged to dock icon: ' + filename)
  395.  
  396.     
  397.     def toggle_prefs(self):
  398.         import digsbyprofile
  399.         if not hasattr(digsbyprofile, 'profile') or digsbyprofile.profile is None:
  400.             return wx.MessageBox(_('Please login first.'), _('Advanced Preferences'))
  401.         
  402.         pref = pref
  403.         import common
  404.         if not __debug__ and sys.REVISION == 'dev' or pref('debug.advanced_prefs', False):
  405.             return None
  406.         
  407.         profile = digsbyprofile.profile
  408.         import prefs as prefs
  409.         if not self.buddy_frame:
  410.             pass
  411.         prefs.edit(profile.prefs, profile.defaultprefs, None)
  412.  
  413.     
  414.     def toggle_crust(self):
  415.         pref = pref
  416.         import common
  417.         if not getattr(sys, 'DEV', False):
  418.             pass
  419.         can_show_console = pref('debug.console', False)
  420.         if not can_show_console:
  421.             return None
  422.         
  423.         self.make_crust()
  424.         self.crust.toggle_shown()
  425.         if self.crust.IsShown():
  426.             self.crust.FocusInput()
  427.         
  428.  
  429.     
  430.     def make_crust(self):
  431.         if not hasattr(self, 'crust') or not (self.crust):
  432.             import gui
  433.             tlws = wx.GetTopLevelWindows()
  434.             self.crust = gui.PyCrustFrame(None)
  435.             if tlws:
  436.                 parent = tlws[0]
  437.                 parent.crust = self.crust
  438.             
  439.         
  440.  
  441.     
  442.     def toggle_sorting(self):
  443.         profile = profile
  444.         import common
  445.         prefs = profile.prefs
  446.         if prefs:
  447.             if prefs.get('buddylist.allow_sorting_change', False):
  448.                 prefs['buddylist.sorting'] = not prefs.get('buddylist.sorting', True)
  449.             
  450.         
  451.  
  452.     
  453.     def not_idle(self, e = None):
  454.         pref = pref
  455.         profile = profile
  456.         import common
  457.         import digsbyprofile as d
  458.         if not profile.prefs:
  459.             return None
  460.         
  461.         set_idle_after = pref('messaging.idle_after', 20 * d.IDLE_UNIT, type = int)
  462.         GetUserIdleTime = GetUserIdleTime
  463.         import gui.native.helpers
  464.         t = GetUserIdleTime()
  465.         if t < set_idle_after * 1000:
  466.             profile.reset_timers()
  467.             profile.return_from_idle()
  468.         
  469.         self.idletimer.Start()
  470.  
  471.     
  472.     def OnSaved(self):
  473.         log.info('profile.save SUCCESS, shutting down')
  474.         return self.do_shutdown()
  475.  
  476.     
  477.     def OnSaveError(self):
  478.         log.warning('error saving blobs')
  479.         return self.do_shutdown()
  480.  
  481.     
  482.     def DigsbyCleanupAndQuit(self, e = None):
  483.         traceguard = traceguard
  484.         Delegate = Delegate
  485.         import util
  486.         log.info('DigsbyCleanupAndQuit')
  487.         if getattr(self, 'shutting_down', False):
  488.             return None
  489.         
  490.         self.shutting_down = True
  491.         Delegate(self.PreShutdown)()
  492.         log.info('  saving and disconnecting profiles and accounts')
  493.         traceguard.__enter__()
  494.         
  495.         try:
  496.             log.info('destroying main tray icon...')
  497.             if getattr(self, 'tbicon', None) is not None:
  498.                 self.tbicon.Destroy()
  499.                 self.tbicon = None
  500.             
  501.             frame = getattr(self, 'buddy_frame', None)
  502.             if frame:
  503.                 if frame.IsShown():
  504.                     frame.on_close(exiting = True)
  505.                 
  506.                 log.info('destroying %r', frame)
  507.                 frame.on_destroy()
  508.             
  509.             traceguard.__enter__()
  510.             
  511.             try:
  512.                 popup = popup
  513.                 import gui
  514.                 popup.cancel_all()
  515.             finally:
  516.                 pass
  517.  
  518.             for tlw in wx.GetTopLevelWindows():
  519.                 tlw.Close(True)
  520.         finally:
  521.             pass
  522.  
  523.         profile = profile
  524.         import digsbyprofile
  525.         if profile and profile.connection:
  526.             profile.save(success = self.OnSaved, error = self.OnSaveError)
  527.         else:
  528.             self.OnSaved()
  529.  
  530.     
  531.     def OnExit(self, event = None):
  532.         log.info('OnExit')
  533.         log.info('  replacing wx.CallAfter')
  534.         
  535.         wx.CallAfter = lambda f, *a, **k: f(*a, **k)
  536.  
  537.     
  538.     def do_shutdown(self):
  539.         traceguard = traceguard
  540.         import util
  541.         log.info('do_shutdown')
  542.         traceguard.__enter__()
  543.         
  544.         try:
  545.             if USE_SINGLE_INSTANCE:
  546.                 self.StopSingleInstanceServer()
  547.         finally:
  548.             pass
  549.  
  550.         traceguard.__enter__()
  551.         
  552.         try:
  553.             timer = getattr(self, 'tray_refresh_timer', None)
  554.             log.info('  ok')
  555.         finally:
  556.             pass
  557.  
  558.         dbg = log.debug
  559.         info = log.info
  560.         
  561.         def _after_disconnect():
  562.             info('joining with TimeoutThread')
  563.             traceguard.__enter__()
  564.             
  565.             try:
  566.                 timeout_thread = timeout_thread
  567.                 import util.threads
  568.                 timeout_thread.join()
  569.             finally:
  570.                 pass
  571.  
  572.             info('joined with TimeoutThread')
  573.             info('joining with AsyncoreThread')
  574.             traceguard.__enter__()
  575.             
  576.             try:
  577.                 import AsyncoreThread as AsyncoreThread
  578.                 AsyncoreThread.end_thread()
  579.                 AsyncoreThread.join()
  580.             finally:
  581.                 pass
  582.  
  583.             info('joining ThreadPool')
  584.             ThreadPool = ThreadPool
  585.             import util
  586.             ThreadPool().joinAll()
  587.             info('done joining ThreadPool')
  588.             dbg('clean exit.')
  589.             self.ExitMainLoop()
  590.  
  591.         dbg('disconnecting profile')
  592.         traceguard.__enter__()
  593.         
  594.         try:
  595.             profile = profile
  596.             import common
  597.             if profile and hasattr(profile, 'disconnect'):
  598.                 profile.disconnect(success = _after_disconnect)
  599.             else:
  600.                 _after_disconnect()
  601.         finally:
  602.             pass
  603.  
  604.  
  605.     
  606.     def init_hotkeys(self):
  607.         input = input_manager
  608.         import gui.input.inputmanager
  609.         skin = skin
  610.         import gui
  611.         platformName = platformName
  612.         import config
  613.         input.AddGlobalContext(_('Global Shortcuts'), 'Global')
  614.         if getattr(sys, 'DEV', False):
  615.             input.AddGlobalContext(_('Debug Global Shortcuts'), 'Debug')
  616.         
  617.         input.AddClassContext(_('Text Controls'), 'TextControls', wx.TextCtrl)
  618.         resdir = skin.resourcedir()
  619.         KEYS_YAML = 'keys.yaml'
  620.         yaml_sources = (resdir / KEYS_YAML, resdir / platformName / KEYS_YAML)
  621.         for yaml in yaml_sources:
  622.             if yaml.exists():
  623.                 log.info('loading keyboard shortcuts from %s', yaml)
  624.                 input.LoadKeys(yaml)
  625.                 continue
  626.         
  627.         actions = [
  628.             ('TextControls.SelectAll', (lambda textctrl: textctrl.SetSelection(-1, -1))),
  629.             ('TextControls.DeletePreviousWord', 'gui.toolbox.DeleteWord'),
  630.             (('Global.DigsbyShell.ToggleShow',), (lambda win: self.toggle_crust())),
  631.             (('Global.AdvancedPrefs.ToggleShow',), (lambda win: self.toggle_prefs())),
  632.             (('Global.Skin.Reload',), (lambda win: skin.reload())),
  633.             (('BuddyList.Sorting.Toggle',), (lambda win: self.toggle_sorting())),
  634.             ('Debug.XMLConsole', 'common.commandline.xmlconsole'),
  635.             ('Debug.JavaScriptConsole', 'gui.browser.jsconsole.show_console')]
  636.         addcb = input.AddActionCallback
  637.         for name, action_cb in actions:
  638.             addcb(name, action_cb)
  639.         
  640.         input.BindWxEvents(self)
  641.  
  642.     
  643.     def AddGlobalHotkey(self, keys, callback):
  644.         id = self.next_hotkey_id
  645.         self.next_hotkey_id += 1
  646.         keycodes = keycodes
  647.         import gui.toolbox
  648.         (modifiers, key) = keycodes(keys)
  649.         self.buddy_frame.RegisterHotKey(id, modifiers, key)
  650.         self.buddy_frame.Bind(wx.EVT_HOTKEY, callback, id = id)
  651.         self.global_hotkeys[(modifiers, key, callback)] = id
  652.  
  653.     
  654.     def RemoveGlobalHotkey(self, keys, callback):
  655.         keycodes = keycodes
  656.         import gui.toolbox
  657.         (modifiers, key) = keycodes(keys)
  658.         id = self.global_hotkeys.pop((modifiers, key, callback))
  659.         self.buddy_frame.UnregisterHotKey(id)
  660.  
  661.     
  662.     def should_check_for_updates(self):
  663.         retval = True
  664.         reason = None
  665.         if not sys.opts.allow_update:
  666.             retval = False
  667.             reason = 'sys.opts.allow_updates == False'
  668.         
  669.         if platform.platform().find('Windows-2000') != -1:
  670.             retval = False
  671.             reason = 'Windows 2000'
  672.         
  673.         if not retval:
  674.             log.info('Not checking for updates because: %r', reason)
  675.         
  676.         return retval
  677.  
  678.     
  679.     def _manifest_path_from_yaml(self, yaml_loc):
  680.         import syck as syck
  681.         import urllib2 as urllib2
  682.         urlopen_ts = urlopen_ts
  683.         import AutoUpdate
  684.         
  685.         try:
  686.             response = urlopen_ts(yaml_loc)
  687.         except urllib2.URLError:
  688.             e = None
  689.             log.error('Couldnt get yaml (%r): %r', yaml_loc, e)
  690.             return sentinel
  691.         except Exception:
  692.             e = None
  693.             log.error('update failed: Error opening %r for reading. (%r)', yaml_loc, e)
  694.  
  695.         
  696.         try:
  697.             data = response.read()
  698.         except Exception:
  699.             return sentinel
  700.  
  701.         
  702.         try:
  703.             ui = syck.load(data)
  704.         except Exception:
  705.             print_exc()
  706.             ui = None
  707.  
  708.         if ui is None:
  709.             return sentinel
  710.         
  711.         platformName = platformName
  712.         import config
  713.         all = ui.get('all', { })
  714.         if not ui.get(platformName, None):
  715.             pass
  716.         mine = { }
  717.         release_type = self._get_release_type()
  718.         merged = all.copy()
  719.         merged.update(mine)
  720.         manifest_path = merged.get(release_type, merged.get('release', None))
  721.         if manifest_path is None:
  722.             return sentinel
  723.         else:
  724.             return manifest_path
  725.  
  726.     
  727.     def _get_release_type(self):
  728.         import stdpaths
  729.         tag = None
  730.         
  731.         try:
  732.             
  733.             try:
  734.                 f = _[2]
  735.                 tag = f.readline().strip()
  736.             finally:
  737.                 pass
  738.  
  739.         except Exception:
  740.             pass
  741.  
  742.         if not tag:
  743.             tag = 'release'
  744.         
  745.         return tag
  746.  
  747.     
  748.     def check_for_updates(self, manifest_path_path, success = None, error = None):
  749.         import sys
  750.         import hashlib as hashlib
  751.         import util.httplib2 as httplib2
  752.         import urlparse as urlparse
  753.         import path
  754.         http_date_to_timestamp = http_date_to_timestamp
  755.         urlopen_ts = urlopen_ts
  756.         import AutoUpdate
  757.         
  758.         def try_and_whine(callable):
  759.             
  760.             try:
  761.                 result = callable()
  762.             except Exception:
  763.                 print >>sys.stderr, 'error calling %s' % util.funcinfo(callable)
  764.                 print >>sys.stderr, 'giving up on update check'
  765.                 print_exc()
  766.                 return sentinel
  767.  
  768.             return result
  769.  
  770.         
  771.         try:
  772.             if manifest_path_path.endswith('.yaml'):
  773.                 manifest_location = self._manifest_path_from_yaml(manifest_path_path)
  774.             else:
  775.                 manifest_location = (None, try_and_whine)((lambda : urlopen_ts(manifest_path_path).read()))
  776.         except Exception:
  777.             (None, None)
  778.             (None, None)
  779.             print_exc()
  780.             manifest_location = sentinel
  781.         except:
  782.             (None, None)
  783.  
  784.         print >>sys.stderr, 'manifest location:', manifest_location
  785.         if manifest_location is sentinel:
  786.             return None if error is not None else None
  787.         
  788.         manifest_url = manifest_location
  789.         conn = httplib2.Http()
  790.         
  791.         try:
  792.             (headers, content) = conn.request(manifest_url, 'HEAD')
  793.         except Exception:
  794.             print_exc()
  795.             headers = { }
  796.  
  797.         rmtime = headers.get('x-amz-meta-mtime', None)
  798.         if rmtime is None:
  799.             rmtime = headers.get('last-modified', None)
  800.             if rmtime is not None:
  801.                 rmtime = http_date_to_timestamp(rmtime)
  802.             
  803.         
  804.         if rmtime is not None:
  805.             
  806.             try:
  807.                 rmtime = int(rmtime)
  808.             except (TypeError, ValueError):
  809.                 rmtime = None
  810.             except:
  811.                 None<EXCEPTION MATCH>(TypeError, ValueError)
  812.             
  813.  
  814.         None<EXCEPTION MATCH>(TypeError, ValueError)
  815.         import util
  816.         prog_dir = util.program_dir()
  817.         mymanifest_path = path.path(prog_dir) / path.path(manifest_location).splitpath()[-1]
  818.         print >>sys.stderr, mymanifest_path
  819.         needs_update = True
  820.         if mymanifest_path.exists():
  821.             lmtime = int(mymanifest_path.mtime)
  822.         else:
  823.             lmtime = 0
  824.         if lmtime == rmtime:
  825.             print >>sys.stderr, 'Local MTime matches remote. Not downloading manifest. (local=%r, remote=%r)' % (lmtime, rmtime)
  826.             needs_update = False
  827.         else:
  828.             print >>sys.stderr, 'MTime mismatch. Downloading manifest. (local=%r, remote=%r)' % (lmtime, rmtime)
  829.             if mymanifest_path.exists():
  830.                 mymanifest_digest = mymanifest_path.read_md5()
  831.             else:
  832.                 mymanifest_digest = None
  833.             manifest_resp = (None, try_and_whine)((lambda : urlopen_ts(manifest_location)))
  834.             if manifest_resp is sentinel:
  835.                 return None if error is not None else None
  836.             
  837.             if 'gzip' in manifest_resp.headers.get('Content-Encoding', ''):
  838.                 import gzip
  839.                 import StringIO as StringIO
  840.                 manifest_resp = gzip.GzipFile(fileobj = StringIO.StringIO(manifest_resp.read()))
  841.             
  842.             webman_hash = hashlib.md5()
  843.             bytes = manifest_resp.read(8192)
  844.             while bytes:
  845.                 webman_hash.update(bytes)
  846.                 bytes = manifest_resp.read(8192)
  847.             manifest_resp.close()
  848.             webdigest = webman_hash.digest()
  849.             print >>sys.stderr, repr(mymanifest_digest), repr(webdigest), mymanifest_digest == webdigest
  850.             if mymanifest_digest == webdigest:
  851.                 needs_update = False
  852.             
  853.         if sys.opts.force_update:
  854.             needs_update = True
  855.         
  856.         if success is not None:
  857.             success(needs_update, manifest_location)
  858.         
  859.  
  860.     
  861.     def OnRaiseBuddyList(self, e = None):
  862.         frame = self.buddy_list
  863.         docker = frame.docker
  864.         if docker.AutoHide and docker.docked:
  865.             if docker.autohidden:
  866.                 docker.ComeBack()
  867.             
  868.             frame.Raise()
  869.         elif not frame.IsActive():
  870.             frame.Raise()
  871.         
  872.  
  873.     
  874.     def OnShowHideBuddylist(self, e = None):
  875.         frame = self.buddy_frame
  876.         docker = getattr(frame, 'docker', None)
  877.         if docker is not None and frame.IsShown():
  878.             if getattr(docker, 'Enabled', False) and docker.docked:
  879.                 if docker.autohidden:
  880.                     docker.ComeBack()
  881.                 
  882.                 frame.Raise()
  883.                 return None
  884.             
  885.         
  886.         shown = frame.Visible
  887.         frame.Show(not shown)
  888.         if not shown:
  889.             if frame.IsIconized():
  890.                 frame.Iconize(False)
  891.             
  892.             frame.Raise()
  893.         
  894.  
  895.  
  896.  
  897. class StdErrFilter(object):
  898.     
  899.     def filter(self, record):
  900.         return record.name != 'stderr'
  901.  
  902.  
  903.  
  904. class MyStdErr(object):
  905.     has_stderr = True
  906.     
  907.     def write(self, s):
  908.         
  909.         try:
  910.             self.stderrlog.error(s.rstrip())
  911.         except:
  912.             pass
  913.  
  914.         if MyStdErr.has_stderr:
  915.             
  916.             try:
  917.                 sys.__stderr__.write(s)
  918.             MyStdErr.has_stderr = False
  919.  
  920.         
  921.  
  922.     
  923.     def flush(self):
  924.         if MyStdErr.has_stderr:
  925.             
  926.             try:
  927.                 sys.__stderr__.flush()
  928.             MyStdErr.has_stderr = False
  929.  
  930.         
  931.  
  932.  
  933.  
  934. def get_logdir():
  935.     return os.path.join(wx.StandardPaths.Get().GetUserLocalDataDir(), 'Logs')
  936.  
  937.  
  938. def get_last_log_file_name():
  939.     return os.path.join(get_logdir(), LOG_FILENAME)
  940.  
  941.  
  942. def setup_log_system():
  943.     global full_loggers
  944.     wx.Log.SetActiveTarget(wx.LogStderr())
  945.     if sys.opts.no_log:
  946.         return None
  947.     
  948.     path = path
  949.     import path
  950.     import traceback as traceback
  951.     DisablingStream = DisablingStream
  952.     DelayedStreamLimiter = DelayedStreamLimiter
  953.     LimitedFileSize = LimitedFileSize
  954.     import fileutil
  955.     sys.stdout = DisablingStream(sys.__stdout__)
  956.     sys.stderr = MyStdErr()
  957.     stderrlog = logging.getLogger('stderr')
  958.     sys.stderr.stderrlog = stderrlog
  959.     root = logging.Logger.root
  960.     root.stream = sys.stderr
  961.     root.setLevel(1)
  962.     gzipFileHandler = gzipFileHandler
  963.     CloseFileHandler = CloseFileHandler
  964.     CSVFormatter = CSVFormatter
  965.     CSV_HEADERS = CSV_HEADERS
  966.     import csvlogging
  967.     logdir = path(get_logdir())
  968.     if not logdir.exists():
  969.         logdir.makedirs()
  970.     
  971.     logfilebase = logfile = logdir / LOG_FILENAME
  972.     N = 2
  973.     while True:
  974.         
  975.         try:
  976.             f = open(logfile, 'wb')
  977.         continue
  978.         print_exc()
  979.         logfile = logfilebase + ' (%d)' % N
  980.         N += 1
  981.         if N > 100:
  982.             raise AssertionError
  983.         
  984.  
  985.         f = open(logfile, 'wb')
  986.         continue
  987.     sys.LOGFILE_NAME = logfile
  988.     f.write(CSV_HEADERS)
  989.     f.close()
  990.     hdlr = CloseFileHandler(DelayedStreamLimiter(LimitedFileSize(sys.LOGFILE_NAME, 20971520, 10485760, initmode = 'ab'), limit = LOG_SPEED_LIMIT, window = LOG_SPEED_WINDOW))
  991.     hdlr.setFormatter(CSVFormatter())
  992.     full_loggers = [
  993.         hdlr]
  994.     root.addHandler(hdlr)
  995.     init_stdout()
  996.     if not __debug__:
  997.         logging.info('logger started - rev %s', sys.REVISION)
  998.     
  999.     print >>sys.stderr, 'testing stderr'
  1000.     print >>sys.stdout, 'testing stdout'
  1001.  
  1002.  
  1003. class ConsoleFormatter(logging.Formatter):
  1004.     
  1005.     def format(self, record):
  1006.         if record.exc_info and not (record.exc_text):
  1007.             record.exc_text = self.formatException(record.exc_info)
  1008.         
  1009.         exc = None if record.exc_text else ''
  1010.         return ''.join([
  1011.             '%-20s' % record.name,
  1012.             record.threadName[:4],
  1013.             '-',
  1014.             '%-4s | ' % record.levelname[:4],
  1015.             '%s' % record.getMessage(),
  1016.             exc])
  1017.  
  1018.  
  1019.  
  1020. def init_stdout():
  1021.     DelayedStreamLimiter = DelayedStreamLimiter
  1022.     import fileutil
  1023.     console = None
  1024.     root = logging.Logger.root
  1025.     
  1026.     try:
  1027.         sys.stdout.write('Testing if sys.stdout is safe...\n')
  1028.     except:
  1029.         root.info('stdout disabled')
  1030.  
  1031.     root.info('stdout enabled')
  1032.     console = logging.StreamHandler(DelayedStreamLimiter(sys.stdout, limit = LOG_SPEED_LIMIT, window = LOG_SPEED_WINDOW))
  1033.     console.setLevel(1)
  1034.     console.setFormatter(ConsoleFormatter())
  1035.     if console is not None:
  1036.         logging.getLogger('').addHandler(console)
  1037.     
  1038.     if console is not None:
  1039.         console.addFilter(StdErrFilter())
  1040.     
  1041.  
  1042. startup_begin = 0
  1043.  
  1044. def check_dependencies():
  1045.     
  1046.     try:
  1047.         import tlslite as tlslite
  1048.     except ImportError:
  1049.         pass
  1050.  
  1051.     print >>sys.stderr, 'WARNING! tlslite is on PYTHONPATH, and will cause SSL problems. Please remove it: %r' % tlslite.__file__
  1052.  
  1053.  
  1054. def set_update_tag():
  1055.     tag = sys.opts.updatetag
  1056.     if tag is not None:
  1057.         import stdpaths
  1058.         
  1059.         try:
  1060.             
  1061.             try:
  1062.                 f = _[2]
  1063.                 f.write(tag)
  1064.                 f.write('\n')
  1065.             finally:
  1066.                 pass
  1067.  
  1068.         except Exception:
  1069.             pass
  1070.         except:
  1071.             None<EXCEPTION MATCH>Exception
  1072.         
  1073.  
  1074.     None<EXCEPTION MATCH>Exception
  1075.  
  1076.  
  1077. def main():
  1078.     global startup_begin
  1079.     startup_begin = time()
  1080.     platformName = platformName
  1081.     import config
  1082.     if platformName == 'win' and sys.opts.crashreport:
  1083.         return send_crash_report()
  1084.     
  1085.     if sys.opts.profile:
  1086.         set_profilers_enabled = set_profilers_enabled
  1087.         import util
  1088.         set_profilers_enabled(True)
  1089.     
  1090.     digsby_app = DigsbyApp()
  1091.     wx.ConfigBase.Set(wx.FileConfig())
  1092.     setup_log_system()
  1093.     log_system_info()
  1094.     digsby_app.ShowSplash()
  1095.     set_update_tag()
  1096.     if sys.opts.profile:
  1097.         currentThread = currentThread
  1098.         import threading
  1099.         use_profiler = use_profiler
  1100.         all_profilers = all_profilers
  1101.         import util
  1102.         if sys.opts.profile > 1:
  1103.             RepeatTimer = RepeatTimer
  1104.             import util
  1105.             
  1106.             def get_reports():
  1107.                 print '\n\n'.join((lambda .0: for p in .0:
  1108. p.report())(all_profilers().itervalues()))
  1109.  
  1110.             digsby_app._profile_timer = RepeatTimer(30, get_reports)
  1111.             digsby_app._profile_timer.start()
  1112.         
  1113.         return use_profiler(currentThread(), digsby_app.MainLoop)
  1114.     else:
  1115.         return digsby_app.MainLoop()
  1116.  
  1117.  
  1118. def send_crash_report():
  1119.     a = wx.PySimpleApp()
  1120.     format_exc = format_exc
  1121.     import traceback
  1122.     set_app_info(a)
  1123.     CrashDialog = CrashDialog
  1124.     import crashgui
  1125.     msg = _('There was an error submitting your crash report.')
  1126.     
  1127.     try:
  1128.         diag = CrashDialog()
  1129.         diag.CenterOnScreen()
  1130.         diag.RequestUserAttention()
  1131.         if wx.ID_OK == diag.ShowModal():
  1132.             import util.diagnostic as d
  1133.             last_log = get_last_log_file_name()
  1134.             diagobj = d.load_crash(sys.opts.crashreport, last_log, username = sys.opts.crashuser, description = diag.Description)
  1135.             if diagobj.succeeded:
  1136.                 msg = _('Crash report submitted successfully.')
  1137.             
  1138.         else:
  1139.             return None
  1140.     except Exception:
  1141.         print_exc()
  1142.  
  1143.     msg += '\n\n' + _('Would you like to restart Digsby now?')
  1144.     if wx.YES == wx.MessageBox(msg, _('Crash Report'), style = wx.YES_NO | wx.YES_DEFAULT):
  1145.         cmd = sys.executable.decode(sys.getfilesystemencoding())
  1146.         if not getattr(sys, 'frozen', False) == 'windows_exe':
  1147.             cmd += ' ' + sys.argv[0]
  1148.         
  1149.         wx.Execute(cmd)
  1150.     
  1151.  
  1152.  
  1153. def log_system_info():
  1154.     import locale as locale
  1155.     startup_time = (time() - startup_begin) * 1000
  1156.     info = log.info
  1157.     info('Digsby rev %s', sys.REVISION)
  1158.     info('started up in %s ms', startup_time)
  1159.     info(' '.join(wx.PlatformInfo) + ' wx v' + '.'.join((lambda .0: for c in .0:
  1160. str(c))(wx.VERSION)))
  1161.     info('Platform: %r', ' '.join(platform.uname()).strip())
  1162.     info('Python ' + sys.version)
  1163.     info('locale: ' + str(locale.getdefaultlocale()))
  1164.     info('user local data dir: %r', wx.StandardPaths.Get().GetUserLocalDataDir())
  1165.     info('__debug__ is %r', __debug__)
  1166.     info('updatetag is %r', sys.opts.updatetag)
  1167.  
  1168.  
  1169. def set_app_info(app):
  1170.     app.SetAppName(APP_NAME)
  1171.     app.SetVendorName(u'dotSyntax')
  1172.     app.SetAppName(APP_NAME)
  1173.     app.SetClassName(APP_NAME)
  1174.  
  1175. if __name__ == '__main__':
  1176.     raise AssertionError('run Digsby.py')
  1177.  
  1178.